﻿namespace Triad.Controls
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Reflection;
    using System.Text;
    /// <summary>
    /// Data Conversion Class - used when DataTable is not the datasource.
    /// </summary>
    /// <remarks>
    /// Author: tim.fischer,   8/25/2008 - 3:03 PM
    /// Modified By: 
    /// </remarks>
    class DataConversion
    {
        /// <summary>
        /// Converts the data view to string.
        /// </summary>
        /// <param name="srcDataView">The SRC data view.</param>
        /// <param name="Delimiter">The delimiter.</param>
        /// <param name="Separator">The separator.</param>
        /// <returns></returns>
        /// <remarks>
        /// Author: tim.fischer,   8/26/2008 - 9:04 AM
        /// Modified By: 
        /// </remarks>
        public static string ConvertDataViewToString(DataView srcDataView, string Delimiter, string Separator, bool HideFirstTwoRows)
        {
            var resultBuilder = new StringBuilder { Length = 0 };


            int i = 0;

            foreach (DataColumn aCol in srcDataView.Table.Columns)
            {
                if (i < 2 && HideFirstTwoRows)
                {
                    i++; continue;
                }
                    if ((Delimiter != null) && (Delimiter.Trim().Length > 0))
                    {
                        resultBuilder.Append(Delimiter);
                    }
                    resultBuilder.Append("\""+aCol.ColumnName+"\"");
                    if ((Delimiter != null) && (Delimiter.Trim().Length > 0))
                    {
                        resultBuilder.Append(Delimiter);
                    }
                    resultBuilder.Append(Separator);
                
                

            }
            if (resultBuilder.Length > Separator.Trim().Length)
            {
                resultBuilder.Length = resultBuilder.Length - Separator.Trim().Length;
            }
            resultBuilder.Append(Environment.NewLine);

            foreach (DataRowView aRow in srcDataView)
            {
                i = 0;
                foreach (DataColumn aCol in srcDataView.Table.Columns)
                {
                        if (i < 2 && HideFirstTwoRows)
                        {
                            i++; continue;
                        }

                        if ((Delimiter != null) && (Delimiter.Trim().Length > 0))
                        {
                            resultBuilder.Append(Delimiter);
                        }
                        resultBuilder.Append("\""+aRow[aCol.ColumnName].ToString()+"\"");
                        if ((Delimiter != null) && (Delimiter.Trim().Length > 0))
                        {
                            resultBuilder.Append(Delimiter);
                        }
                        resultBuilder.Append(Separator);

                }

                resultBuilder.Length = resultBuilder.Length - 1;
                resultBuilder.Append(Environment.NewLine);
            }

            if (resultBuilder.Length > 0)
            {
                return resultBuilder.ToString();
            }
            return string.Empty;
        }

        private static void FillData(IEnumerable<PropertyInfo> properties, DataTable dt, Object o)
        {
            DataRow dr = dt.NewRow();
            foreach (PropertyInfo pi in properties)
                dr[pi.Name] = pi.GetValue(o, null);
            dt.Rows.Add(dr);
        }

        //All the Properties for the class array are converted to columns. We can always add a 
        //condition to include required columns alone.
        private static DataTable CreateDataTable(IEnumerable<PropertyInfo> properties)
        {
            var dt = new DataTable();
            foreach (var pi in properties)
            {
                var dc = new DataColumn { ColumnName = pi.Name, DataType = pi.PropertyType };

                dt.Columns.Add(dc);
            }
            return dt;
        }

        /// <summary>
        /// Converts array objects to data table.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <returns></returns>
        /// <remarks>
        /// Author: tim.fischer,   5/19/2008 - 10:33 AM
        /// Modified By: 
        /// </remarks>
        public static DataTable ConvertToDataTable(Object[] array)
        {
            var properties = array.GetType().GetElementType().GetProperties();
            var dt = CreateDataTable(properties);
            dt.Namespace = "tfLV_NS";
            dt.TableName = "tfLV_TN";

            if (array.Length != 0)
            {
                foreach (var o in array)
                    FillData(properties, dt, o);
            }
            return dt;
        }

        /// <summary>
        /// Converts an IEnumerable to an ADOTable to be used with the grid.
        /// </summary>
        /// <param name="query">The IEnumerable.</param>
        /// <returns></returns>
        /// <remarks>
        /// Author: tim.fischer,   8/26/2008 - 9:08 AM
        /// Modified By: 
        /// </remarks>
        public static DataTable ToADOTable(IEnumerable query)
        {
            var dtReturn = new DataTable();
            PropertyInfo[] columnProperties = null;

            foreach (var record in query)
            {
                // use reflection to get column names for the table, only first time, others will follow
                if (columnProperties == null)
                {
                    columnProperties = record.GetType().GetProperties();
                    foreach (var propertyInfo in columnProperties)
                    {
                        // sort out the issue of nullable types
                        var columnType = propertyInfo.PropertyType;
                        if ((columnType.IsGenericType) && (columnType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        {
                            columnType = columnType.GetGenericArguments()[0];
                        }

                        // add a column to the table
                        dtReturn.Columns.Add(new DataColumn(propertyInfo.Name, columnType));
                    }
                }

                var dataRow = dtReturn.NewRow();

                foreach (PropertyInfo propertyInfo in columnProperties)
                {
                    dataRow[propertyInfo.Name] = propertyInfo.GetValue(record, null) ?? DBNull.Value;
                }

                dtReturn.Rows.Add(dataRow);
            }

            return dtReturn;
        }
    }
}
